﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using iWare.Wms.Core;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Yitter.IdGenerator;

namespace iWare.Wms.Application.PDA
{
    /// <summary>
    /// 组盘入库服务
    /// </summary>
    [Route("api/BindHousing")]
    [ApiDescriptionSettings("PDA", Name = "BindHousing", Order = 1)]

    public class BindHousingService : IDynamicApiController, ITransient
    {
        private readonly IRepository<WareArea, MasterDbContextLocator> _wareAreaRep; //库区仓储
        private readonly IRepository<WareAgvTask, MasterDbContextLocator> _wareAgvTaskRep; //AGV任务仓储
        private readonly IRepository<WareMaterial, MasterDbContextLocator> _wareMaterialRep; //物料仓储
        private readonly IRepository<WareContainer, MasterDbContextLocator> _wareContainerRep; //容器仓储
        private readonly IRepository<WareLocation, MasterDbContextLocator> _wareLocationRep; //库位仓储
        private readonly IRepository<WareTask, MasterDbContextLocator> _wareTaskRep; //任务仓储
        private readonly IRepository<WareStock, MasterDbContextLocator> _wareStockRep; //库存仓储
        private readonly IRepository<WareSortOrder, MasterDbContextLocator> _wareSortOrderRep; //分拣仓储
        private readonly IRepository<GoodsDelivery, MasterDbContextLocator> _goodsDeliveryRep; //送货单仓储
        private readonly IRepository<CollectDeliveryDetails, MasterDbContextLocator> _collectDeliveryDetailsRep; //收货明细仓储
        private readonly IRepository<WareContainerVsMaterial, MasterDbContextLocator> _wareContainerVsMaterialRep; //容器与物料关系仓储
        private readonly IRepository<WareLocationVsContainer, MasterDbContextLocator> _wareLocationVsContainerRep; //库位与容器关系仓储
        private readonly IRepository<v_materialtag_project, MasterDbContextLocator> _vMaterialtagProjectRep; //物料与项目试图仓储
        private readonly AgvService _agvService; //AGV服务

        #region 默认
        /// <summary>
        /// 默认
        /// </summary>
        /// <param name="wareAreaRep"></param>
        /// <param name="wareAgvTaskRep"></param>
        /// <param name="wareMaterialRep"></param>
        /// <param name="wareContainerRep"></param>
        /// <param name="wareLocationRep"></param>
        /// <param name="wareTaskRep"></param>
        /// <param name="wareStockRep"></param>
        /// <param name="wareSortOrderRep"></param>
        /// <param name="goodsDeliveryRep"></param>
        /// <param name="collectDeliveryDetailsRep"></param>
        /// <param name="wareContainerVsMaterialRep"></param>
        /// <param name="wareLocationVsContainerRep"></param>
        /// <param name="vMaterialtagProjectRep"></param>
        /// <param name="agvService"></param>
        public BindHousingService(
            IRepository<WareArea, MasterDbContextLocator> wareAreaRep,
            IRepository<WareAgvTask, MasterDbContextLocator> wareAgvTaskRep,
            IRepository<WareMaterial, MasterDbContextLocator> wareMaterialRep,
            IRepository<WareContainer, MasterDbContextLocator> wareContainerRep,
            IRepository<WareLocation, MasterDbContextLocator> wareLocationRep,
            IRepository<WareTask, MasterDbContextLocator> wareTaskRep,
            IRepository<WareStock, MasterDbContextLocator> wareStockRep,
            IRepository<WareSortOrder, MasterDbContextLocator> wareSortOrderRep,
            IRepository<GoodsDelivery, MasterDbContextLocator> goodsDeliveryRep,
            IRepository<CollectDeliveryDetails, MasterDbContextLocator> collectDeliveryDetailsRep,
            IRepository<WareContainerVsMaterial, MasterDbContextLocator> wareContainerVsMaterialRep,
            IRepository<WareLocationVsContainer, MasterDbContextLocator> wareLocationVsContainerRep,
            IRepository<v_materialtag_project, MasterDbContextLocator> vMaterialtagProjectRep,
            AgvService agvService
        )
        {
            _wareAreaRep = wareAreaRep;
            _wareAgvTaskRep = wareAgvTaskRep;
            _wareMaterialRep = wareMaterialRep;
            _wareContainerRep = wareContainerRep;
            _wareLocationRep = wareLocationRep;
            _wareTaskRep = wareTaskRep;
            _wareStockRep = wareStockRep;
            _wareSortOrderRep = wareSortOrderRep;
            _goodsDeliveryRep = goodsDeliveryRep;
            _collectDeliveryDetailsRep = collectDeliveryDetailsRep;
            _wareContainerVsMaterialRep = wareContainerVsMaterialRep;
            _wareLocationVsContainerRep = wareLocationVsContainerRep;
            _vMaterialtagProjectRep = vMaterialtagProjectRep;
            _agvService = agvService;
        }
        #endregion

        #region 一键入库代码
        /// <summary>
        /// 查询自动库区
        /// </summary>
        /// <returns></returns>
        [HttpGet("AreaList")]
        public async Task<List<WareArea>> AreaList()
        {
            return await _wareAreaRep.DetachedEntities
                .Where(z => z.AreaType == AreaTypeEnum.ZD).ToListAsync();
        }

        /// <summary>
        /// 查询非自动库区
        /// </summary>
        /// <returns></returns>
        [HttpGet("OtherAreaList")]
        public async Task<List<WareArea>> OtherAreaListIn()
        {
            return await _wareAreaRep.DetachedEntities
                .Where(z => z.AreaType == AreaTypeEnum.XN || z.AreaType == AreaTypeEnum.NZD).ToListAsync();
        }

        /// <summary>
        /// 根据送货单查询物料信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("CollectModelList")]
        public async Task<List<WareContainerVsMaterialOutput>> CollectModelList(CollectcxInput input)
        {
            if (input.wareContainerVsMaterials == null) input.wareContainerVsMaterials = new List<WareContainerVsMaterialOutput>();
            //先判断该送货单是否已经扫描过
            var isExit = input.wareContainerVsMaterials.Any(p => p.DeliveryNo == input.DeliveryNo);
            if (isExit) throw Oops.Oh("该送货单已经扫描");


            //检查收货表物料信息
            var collectModel = await _collectDeliveryDetailsRep.Where(p => p.CollectDelivery.DeliveryNo == input.DeliveryNo).ToListAsync();
            if (collectModel.Count == 0) throw Oops.Oh("该送货单无收货信息");
            //var ListWareContainerVsMaterial = new List<WareContainerVsMaterialOutput>();
            foreach (var item in collectModel)
            {
                // 查询物料基础信息
                var materialModel = await _wareMaterialRep.FirstOrDefaultAsync(p => p.Code == item.Code);
                if (materialModel == null)
                {
                    // 添加物料基础信息
                    materialModel = new WareMaterial()
                    {
                        Code = item.Code,
                        Name = item.Name,
                        SpecificationModel = item.SpecificationModel,
                        Unit = item.Unit,
                        InspectionMethod = item.InspectionMethod,
                        Quantity = item.CollectQuantity,
                        BrandName = item.BrandName,
                        SupplerCode = item.SupplierInfoCode,
                    };
                    await _wareMaterialRep.InsertAsync(materialModel);
                }

                var hegeQuatity = new decimal(1.00); // 定义合格数

                // 物料检验方式是免检，直接显示收货数量
                if (item.InspectionMethod == InspectionMethodEnum.mianjian)
                    hegeQuatity = item.CollectQuantity;
                // 质检后质检结果是合格或者让步接收，合格数直接显示质检数量
                else if (item.IsQuality == YesOrNot.Y && item.QualityResult == QualityEnum.HeGe || item.QualityResult == QualityEnum.RangBu)
                    hegeQuatity = item.CollectQuantity;//合格数量
                else
                    hegeQuatity = item.CollectQuantity - item.QualityNumber; //合格数量

                if (item.WarehousingQuantity < hegeQuatity)
                {
                    var wareContainerVsMaterialModel = input.wareContainerVsMaterials.FirstOrDefault(p => p.Code == item.Code);
                    if (wareContainerVsMaterialModel != null)
                    {
                        wareContainerVsMaterialModel.BindQuantity += hegeQuatity - item.WarehousingQuantity;
                    }
                    else
                    {
                        wareContainerVsMaterialModel = item.Adapt<WareContainerVsMaterialOutput>();
                        wareContainerVsMaterialModel.SpecificationModel = item.SpecificationModel;
                        wareContainerVsMaterialModel.InspectionMethod = item.InspectionMethod;
                        wareContainerVsMaterialModel.Unit = item.Unit;
                        wareContainerVsMaterialModel.BindQuantity = hegeQuatity - item.WarehousingQuantity;
                        wareContainerVsMaterialModel.MaterialId = materialModel.Id;
                        wareContainerVsMaterialModel.DeliveryNo = input.DeliveryNo;
                        wareContainerVsMaterialModel.ExpirationTime = DateTimeOffset.Now;
                        input.wareContainerVsMaterials.Add(wareContainerVsMaterialModel);
                    }
                }
            }
            return input.wareContainerVsMaterials;
        }

        /// <summary>
        ///扫描物料二维码
        /// </summary>
        /// <returns></returns>
        [HttpPost("MaterialByScan")]
        public async Task<List<WareContainerVsMaterialOutput>> MaterialByScan(OQCodeInput input)
        {
            if (input.wareContainerVsMaterials == null) input.wareContainerVsMaterials = new List<WareContainerVsMaterialOutput>();
            //先判断物料二维码是否已存在
            var isExit = input.wareContainerVsMaterials.Any(p => p.Code == input.Code);
            if (isExit) throw Oops.Oh("物料标签已存在");

            //查询收货信息
            var collectModelTwo = await _collectDeliveryDetailsRep.DetachedEntities.Where(p => p.Code == input.Code).ProjectToType<CollectDeliveryDetails>().ToListAsync();
            // 查询物料基础信息
            var materialModel = await _wareMaterialRep.FirstOrDefaultAsync(p => p.Code == input.Code);
            if (materialModel == null && collectModelTwo.Count == 0) throw Oops.Oh("无该物料信息");
            if (materialModel == null && collectModelTwo.Count != 0)
            {
                // 添加物料基础信息
                materialModel = new WareMaterial()
                {
                    Code = collectModelTwo.FirstOrDefault().Code,
                    Name = collectModelTwo.FirstOrDefault().Name,
                    SpecificationModel = collectModelTwo.FirstOrDefault().SpecificationModel,
                    Unit = collectModelTwo.FirstOrDefault().Unit,
                    InspectionMethod = collectModelTwo.FirstOrDefault().InspectionMethod,
                    Quantity = collectModelTwo.FirstOrDefault().CollectQuantity,
                    BrandName = collectModelTwo.FirstOrDefault().BrandName,
                    SupplerCode = collectModelTwo.FirstOrDefault().SupplierInfoCode,
                };
                await _wareMaterialRep.InsertAsync(materialModel);
            }

            var wareContainerVsMaterialModel = new WareContainerVsMaterialOutput();
            foreach (var item in collectModelTwo)
            {
                var hegeQuatity = new decimal(1.00); // 定义合格数

                // 物料检验方式是免检，直接显示收货数量
                if (item.InspectionMethod == InspectionMethodEnum.mianjian)
                    hegeQuatity = item.CollectQuantity;
                // 质检后质检结果是合格或者让步接收，合格数直接显示质检数量
                else if (item.IsQuality == YesOrNot.Y && item.QualityResult == QualityEnum.HeGe || item.QualityResult == QualityEnum.RangBu)
                    hegeQuatity = item.CollectQuantity;//合格数量
                else
                    hegeQuatity = item.CollectQuantity - item.QualityNumber; //合格数量
                if (item.WarehousingQuantity < hegeQuatity)
                {
                    wareContainerVsMaterialModel = input.wareContainerVsMaterials.FirstOrDefault(p => p.Code == item.Code);
                    if (wareContainerVsMaterialModel != null)
                    {
                        wareContainerVsMaterialModel.BindQuantity += hegeQuatity - item.WarehousingQuantity;
                    }
                    else
                    {
                        wareContainerVsMaterialModel = item.Adapt<WareContainerVsMaterialOutput>();
                        wareContainerVsMaterialModel.SpecificationModel = item.SpecificationModel;
                        wareContainerVsMaterialModel.InspectionMethod = item.InspectionMethod;
                        wareContainerVsMaterialModel.Unit = item.Unit;
                        wareContainerVsMaterialModel.BindQuantity = hegeQuatity - item.WarehousingQuantity;
                        wareContainerVsMaterialModel.MaterialId = materialModel.Id;
                        wareContainerVsMaterialModel.DeliveryNo = item.CollectDelivery.DeliveryNo;
                        wareContainerVsMaterialModel.ExpirationTime = DateTime.Now;
                        input.wareContainerVsMaterials.Add(wareContainerVsMaterialModel);
                    }
                    return input.wareContainerVsMaterials;
                }
            }
            //不在送货单中的物料信息
            wareContainerVsMaterialModel.SpecificationModel = materialModel.SpecificationModel;
            wareContainerVsMaterialModel.InspectionMethod = materialModel.InspectionMethod;
            wareContainerVsMaterialModel.Unit = materialModel.Unit;
            wareContainerVsMaterialModel.BindQuantity = new decimal(1.00);
            wareContainerVsMaterialModel.MaterialId = materialModel.Id;
            wareContainerVsMaterialModel.Code = materialModel.Code;
            wareContainerVsMaterialModel.Name = materialModel.Name;
            wareContainerVsMaterialModel.ExpirationTime = DateTime.Now;

            input.wareContainerVsMaterials.Add(wareContainerVsMaterialModel);
            return input.wareContainerVsMaterials;
        }

        /// <summary>
        /// 自动库容器
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("GetHousingContainer")]
        public async Task<ContainerOutput> GetHousingContainer([FromQuery] ContainerInput input)
        {
            //检查托盘
            var wareContainer = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == input.ContainerCode);
            if (wareContainer == null) throw Oops.Oh("容器信息不存在!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.jinyong) throw Oops.Oh("容器已禁用!");

            //判断是否在任务中
            var isExit = await _wareTaskRep.AnyAsync(n => n.TaskStatus != TaskStatusEnum.Complete && n.ContainerCode == input.ContainerCode);
            if (isExit) throw Oops.Oh("容器存在未完成任务!");
            //判断是否分拣完成
            var wareSortOrderCount = await _wareSortOrderRep.DetachedEntities.Where(p => p.ContainerCode == input.ContainerCode && p.SortStatus != SortStatusEnum.Completed).CountAsync();
            if (wareSortOrderCount > 0) throw Oops.Oh("容器存在未分拣物料!");

            var WareContainerVsMaterials = await _wareContainerVsMaterialRep.DetachedEntities
                .Where(p => p.WareContainer.Code == input.ContainerCode && p.ContainerVsMaterialStatus == CommonStatus.ENABLE)
                .ProjectToType<WareContainerVsMaterialOutput>().ToListAsync();

            return new ContainerOutput
            {
                WareContainer = wareContainer.Adapt<WareContainerOutput>(),
                WareContainerVsMaterials = WareContainerVsMaterials,
            };

        }
        /// <summary>
        /// 自动库入库
        /// </summary>
        /// <returns></returns>
        [HttpPost("WarehouseLitikuIn")]
        [UnitOfWork]
        public async Task WarehouseLitikuIn(WarehousingInput input)
        {
            //检查托盘
            var wareContainer = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == input.WareContainer.Code);
            if (wareContainer == null) throw Oops.Oh("容器信息不存在!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.jinyong) throw Oops.Oh("容器已禁用!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.kuwei) throw Oops.Oh("容器已入库!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.fenjian) throw Oops.Oh("容器存在分拣单据!");

            //组盘
            //1.定义单据号,区分是空托盘入库还是物料入库
            var orderNo = "N/A";
            if (input.WareContainerVsMaterials.Count > 0) orderNo = YitIdHelper.NextId().ToString();
            //2.获取组盘记录
            var wareContainerVsMaterialList = await _wareContainerVsMaterialRep.DetachedEntities.Where(p => p.ContainerCode == wareContainer.Code
                && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();

            //3.满足条件进行组盘
            if (input.WareContainerVsMaterials.Count > 0)
            {
                //清除原组盘信息
                foreach (var itemsub in wareContainerVsMaterialList)
                {
                    await _wareContainerVsMaterialRep.DeleteAsync(itemsub);
                }

                //添加新的组盘信息
                foreach (var itemsub in input.WareContainerVsMaterials)
                {
                    if (itemsub.BindQuantity <= 0) continue;
                    var model = itemsub.Adapt<WareContainerVsMaterial>();
                    model.ProjectCode = String.IsNullOrEmpty(itemsub.ProjectCode) ? "N/A" : itemsub.ProjectCode;
                    model.Id = YitIdHelper.NextId();
                    model.OrderNo = orderNo;
                    model.ContainerCode = wareContainer.Code;
                    model.ContainerId = wareContainer.Id;
                    model.ContainerVsMaterialStatus = CommonStatus.ENABLE;
                    model.ExpirationTime = itemsub.ExpirationTime;
                    await _wareContainerVsMaterialRep.InsertAsync(model);
                }
            }

            var WareContainerVsMaterials = await _wareContainerVsMaterialRep.DetachedEntities
                .Where(p => p.WareContainer.Code == wareContainer.Code && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();

            //1.更改托盘状态
            if (orderNo != "N/A")
            {
                wareContainer.ContainerStatus = ContainerStatusEnum.zupan;
                await _wareContainerRep.UpdateAsync(wareContainer);
            }

            //获取库位容器关系
            var wareLocationVsContainerModel = await _wareLocationVsContainerRep.FirstOrDefaultAsync(p => p.ContainerCode == wareContainer.Code && p.LocationVsContainerStatus == CommonStatus.ENABLE);
            if (wareLocationVsContainerModel != null) throw Oops.Oh("托盘存在库位关系中");

            var taskNo = YitIdHelper.NextId().ToString();

            if (input.AreaId == 374444843716677)//立体库
            {
                if (input.TaskModel == TaskModel.SHOUDONG) //手动入库
                {
                    //1.创建任务
                    var taskModel = new WareTask()
                    {
                        OrderNo = orderNo,
                        TaskNo = YitIdHelper.NextId().ToString(),
                        TaskType = TaskType.In,
                        TaskModel = TaskModel.SHOUDONG,
                        TaskName = orderNo == "N/A" ? TaskNameConst.KongTuo_LitikuManualIn : TaskNameConst.Litiku_ManualIn,
                        TaskStatus = TaskStatusEnum.NotProgress,
                        Priority = 2,
                        ContainerCode = wareContainer.Code,
                        FromLocationCode = "N/A",
                        ToLocationCode = "N/A",
                        CreatedUserId = CurrentUserInfo.UserId,
                        CreatedUserName = CurrentUserInfo.Name,
                        IsRead = true,
                        Images = input.Images != null && input.Images.Count > 0 ? string.Join(",", input.Images) : "N/A",
                    };
                    await _wareTaskRep.InsertAsync(taskModel);
                    //执行完成调用工控机上的入库授权服务
                    //await "http://10.10.10.59:8011/LesApi.ashx".GetAsync();
                }
                else if (input.TaskModel == TaskModel.ZIDONG) //自动入库
                {
                    // 调用AGV服务创建指定名称的订单
                    var createTransportOrders = new CreateTransportOrdersInput();
                    createTransportOrders.TaskNo = taskNo;
                    createTransportOrders.intendedVehicle = "Vehicle-0001"; //立体库执行车辆
                    var destList = new List<DestinationsInput>();
                    var dest1 = new DestinationsInput()
                    {
                        locationName = input.AgvCode, //地面站点/上料口
                        operation = "Load cargo:12" //地面层数是12，Load是取货
                    };
                    var dest2 = new DestinationsInput()
                    {
                        locationName = "Location-0016", //[Location-0016]入库对应的输送线
                        operation = "Unload cargo:01" //输送线层数是1，Unload是放货
                    };
                    destList.Add(dest1);
                    destList.Add(dest2);
                    createTransportOrders.destinations = destList;

                    var createTransportOrdersOutput = await _agvService.CreateTransportOrders(createTransportOrders);
                    // 写日志文件
                    Log.Error($"[LitikuIn][createTransportOrdersOutput:{createTransportOrdersOutput.ToJson()}]");

                    if (createTransportOrdersOutput.result == "success")
                    {
                        // 创建AGV入库任务
                        var wareAgvTask = new WareAgvTask()
                        {
                            TaskType = "入库",
                            StartPlace = input.AgvCode, //地面站点/上料口
                            EndPlace = "Location-0016", //[Location-0016]入库对应的输送线
                            TransportOrder = taskNo,
                            AgvState = "TRAVELLING",
                            ContainerCode = input.WareContainer.Code,
                        };
                        await _wareAgvTaskRep.InsertAsync(wareAgvTask);

                        //1.创建任务
                        var taskModel = new WareTask()
                        {
                            OrderNo = orderNo,
                            TaskNo = taskNo,
                            TaskType = TaskType.In,
                            TaskModel = TaskModel.ZIDONG,
                            TaskName = orderNo == "N/A" ? TaskNameConst.KongTuo_LitikuManualIn : TaskNameConst.Litiku_ManualIn,
                            TaskStatus = TaskStatusEnum.NotProgress,
                            Priority = 2,
                            ContainerCode = wareContainer.Code,
                            FromLocationCode = input.AgvCode,
                            ToLocationCode = "N/A",
                            CreatedUserId = CurrentUserInfo.UserId,
                            CreatedUserName = CurrentUserInfo.Name,
                            IsRead = false,
                            Images = input.Images != null && input.Images.Count > 0 ? string.Join(",", input.Images) : "N/A",
                        };
                        await _wareTaskRep.InsertAsync(taskModel);
                    }
                }

            }
            else if (input.AreaId == 374444736143429)//平库
            {
                if (input.TaskModel == TaskModel.SHOUDONG) //手动入库
                {
                    //检查库位
                    var locationModel = await _wareLocationRep.FirstOrDefaultAsync(p => p.AreaID == input.AreaId
                    && p.Code == input.LocationCode);
                    if (locationModel == null) throw Oops.Oh("库位不存在!");
                    if (locationModel.LocationStatus != LocationStatusEnum.kongxian) throw Oops.Oh("库位被占用!");
                    if (locationModel.IsLock == YesOrNot.Y) throw Oops.Oh("库位被锁定!");

                    //修改托盘状态
                    wareContainer.ContainerStatus = ContainerStatusEnum.kuwei;
                    await _wareContainerRep.UpdateAsync(wareContainer);

                    //更新库位
                    locationModel.LocationStatus = LocationStatusEnum.cunhuo;
                    if (orderNo == "N/A") locationModel.IsEmptyContainer = YesOrNot.Y;
                    else locationModel.IsEmptyContainer = YesOrNot.N;
                    await _wareLocationRep.UpdateAsync(locationModel);

                    //构建容器与库位关系表
                    wareLocationVsContainerModel = new WareLocationVsContainer()
                    {
                        LocationId = locationModel.Id,
                        LocationCode = locationModel.Code,
                        ContainerId = wareContainer.Id,
                        ContainerCode = wareContainer.Code,
                        LocationVsContainerStatus = CommonStatus.ENABLE
                    };
                    await _wareLocationVsContainerRep.InsertAsync(wareLocationVsContainerModel);

                    foreach (var itemsub in input.WareContainerVsMaterials)
                    {
                        //更新库存
                        var stockDetailModel = await _wareStockRep.FirstOrDefaultAsync(n => n.ContainerCode == itemsub.ContainerCode
                        && n.ProjectCode == itemsub.ProjectCode && n.Code == itemsub.Code && n.SpecificationModel == itemsub.SpecificationModel);

                        if (stockDetailModel != null)
                        {
                            stockDetailModel.StockQuantity = itemsub.BindQuantity;
                            stockDetailModel.LocationCode = locationModel.Code;
                            stockDetailModel.CurrentQuantity = itemsub.BindQuantity;
                            stockDetailModel.ProjectCode = itemsub.ProjectCode;
                            stockDetailModel.ExpirationTime = itemsub.ExpirationTime;
                            await _wareStockRep.UpdateAsync(stockDetailModel);
                        }
                        else
                        {
                            stockDetailModel = new WareStock()
                            {
                                ProjectCode = itemsub.ProjectCode,
                                Code = itemsub.Code,
                                Name = itemsub.Name,
                                SpecificationModel = itemsub.SpecificationModel,
                                Unit = itemsub.Unit,
                                StockQuantity = itemsub.BindQuantity,
                                CurrentQuantity = itemsub.BindQuantity,
                                ContainerCode = wareContainer.Code,
                                LocationCode = locationModel.Code,
                                XuHao = itemsub.XuHao,
                                BrandName = itemsub.BrandName,
                                ExpirationTime = itemsub.ExpirationTime,
                                CreatedUserId = CurrentUserInfo.UserId,
                                CreatedUserName = CurrentUserInfo.Name,
                                CreatedTime = DateTimeOffset.Now,
                                UpdatedUserId = CurrentUserInfo.UserId,
                                UpdatedUserName = CurrentUserInfo.Name,
                                UpdatedTime = DateTimeOffset.Now
                            };
                            await _wareStockRep.InsertNowAsync(stockDetailModel);
                        }

                        if (!string.IsNullOrEmpty(itemsub.DeliveryNo) && itemsub.DeliveryNo != "N/A")
                        {
                            //更新收货数据入库数量  -- deliveryNo 没有传递
                            var model = await _collectDeliveryDetailsRep.FirstOrDefaultAsync(n => n.ProjectCode == itemsub.ProjectCode
                                 && n.Code == itemsub.Code && n.CollectDelivery.DeliveryNo == itemsub.DeliveryNo);
                            if (model != null)
                            {
                                model.WarehousingQuantity += itemsub.BindQuantity;
                                await _collectDeliveryDetailsRep.UpdateAsync(model);
                            }
                        }
                    }

                    //空托
                    if (orderNo == "N/A")
                    {
                        var stockModel = new WareStock()
                        {
                            ProjectCode = "N/A",
                            Code = "N/A",
                            Name = "N/A",
                            SpecificationModel = "N/A",
                            Unit = "N/A",
                            StockQuantity = 1,
                            CurrentQuantity = 1,
                            ContainerCode = wareContainer.Code,
                            LocationCode = locationModel.Code,
                            XuHao = "N/A",
                            BrandName = "",
                            UpdatedUserId = CurrentUserInfo.UserId,
                            UpdatedUserName = CurrentUserInfo.Name,
                            UpdatedTime = DateTimeOffset.Now
                        };
                        await _wareStockRep.InsertAsync(stockModel);
                    }

                    //1.创建任务
                    var taskModel = new WareTask()
                    {
                        OrderNo = orderNo,
                        TaskNo = YitIdHelper.NextId().ToString(),
                        TaskType = TaskType.In,
                        TaskModel = TaskModel.SHOUDONG,
                        TaskName = orderNo == "N/A" ? TaskNameConst.KongTuo_PingkuManualIn : TaskNameConst.Pingku_ManualIn,
                        TaskStatus = TaskStatusEnum.Complete,
                        Priority = 1,
                        ContainerCode = wareContainer.Code,
                        ToLocationCode = input.LocationCode,
                        FromLocationCode = "N/A",
                        CreatedUserId = CurrentUserInfo.UserId,
                        CreatedUserName = CurrentUserInfo.Name,
                        CreatedTime = DateTime.Now,
                        UpdatedUserId = CurrentUserInfo.UserId,
                        UpdatedUserName = CurrentUserInfo.Name,
                        UpdatedTime = DateTime.Now,
                        Images = input.Images != null && input.Images.Count > 0 ? string.Join(",", input.Images) : "N/A",
                    };
                    await _wareTaskRep.InsertAsync(taskModel);
                }
                else if (input.TaskModel == TaskModel.ZIDONG) //自动入库
                {
                    #region 创建任务
                    //1.创建任务
                    var taskModel = new WareTask()
                    {
                        OrderNo = orderNo,
                        TaskNo = taskNo,
                        TaskType = TaskType.In,
                        TaskModel = TaskModel.ZIDONG,
                        TaskName = orderNo == "N/A" ? TaskNameConst.KongTuo_PingkuAutomaticIn : TaskNameConst.Pingku_AutomaticIn,
                        TaskStatus = TaskStatusEnum.NotProgress,
                        Priority = 1,
                        IsRead = false,
                        ContainerCode = wareContainer.Code,
                        FromLocationCode = input.AgvCode, //入口
                        ToLocationCode = "N/A",
                        CreatedUserId = CurrentUserInfo.UserId,
                        CreatedUserName = CurrentUserInfo.Name,
                        CreatedTime = DateTimeOffset.Now,
                        UpdatedUserId = CurrentUserInfo.UserId,
                        UpdatedUserName = CurrentUserInfo.Name,
                        UpdatedTime = DateTimeOffset.Now,
                        Images = input.Images != null && input.Images.Count > 0 ? string.Join(",", input.Images) : "N/A"
                    };
                    if (!string.IsNullOrEmpty(input.LocationCode))
                    {
                        var locationModel = await _wareLocationRep.FirstOrDefaultAsync(p => p.Code == input.LocationCode && p.IsLock == YesOrNot.N && p.LocationStatus == LocationStatusEnum.kongxian);
                        if (locationModel == null) throw Oops.Oh("库位不存在或不能使用!");

                        taskModel.ToLocationCode = input.LocationCode;
                    }
                    await _wareTaskRep.InsertAsync(taskModel);

                    #endregion

                    #region 创建AGV任务
                    // 调用AGV服务创建指定名称的订单 第一段任务
                    var agvModel = new CreateOrdersedInput()
                    {
                        TaskNo = taskNo + "-1",
                        locationName = input.AgvCode,
                        operation = "Load cargo:12"
                    };
                    var createTransportOrdersOutput = await _agvService.CreateLoadOrders(agvModel);

                    if (createTransportOrdersOutput.result == "success")
                    {
                        // 创建AGV入库任务
                        var wareAgvTask = new WareAgvTask()
                        {
                            TaskType = "入库",
                            StartPlace = input.AgvCode, //地面站点/上料口
                            EndPlace = "9067", //外形检测点位
                            TransportOrder = taskNo,
                            AgvState = "PRISTINE",
                            ContainerCode = input.WareContainer.Code
                        };
                        await _wareAgvTaskRep.InsertAsync(wareAgvTask);
                    }
                    #endregion
                }
            }
        }

        /// <summary>
        /// 非自动库区获取库位信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("OtherHousingLocation")]
        public async Task<List<WareContainerVsMaterialOutput>> OtherHousingLocation([FromQuery] LocationInput input)
        {
            //检查库位
            var wareLocation = await _wareLocationRep.FirstOrDefaultAsync(z => z.Code == input.LocationCode);
            if (wareLocation == null) throw Oops.Oh("库位信息不存在!");
            if (wareLocation.LocationStatus == LocationStatusEnum.jinyong) throw Oops.Oh("库位已禁用!");

            var locationVsContainer = await _wareLocationVsContainerRep.FirstOrDefaultAsync(z => z.LocationVsContainerStatus == CommonStatus.ENABLE && z.LocationCode == input.LocationCode);
            if (locationVsContainer != null)
            {
                var WareContainerVsMaterials = await _wareContainerVsMaterialRep.DetachedEntities
                .Where(p => p.WareContainer.Code == locationVsContainer.ContainerCode && p.ContainerVsMaterialStatus == CommonStatus.ENABLE)
                .ProjectToType<WareContainerVsMaterialOutput>().ToListAsync();
                return WareContainerVsMaterials;
            }
            return null;
        }
        /// <summary>
        /// 非自动库区入库
        /// </summary>
        /// <returns></returns>
        [HttpPost("OtherLitikuIn")]
        [UnitOfWork]
        public async Task OtherLitikuIn(WarehousingInput input)
        {
            // 根据所属库区ID查询库区信息
            var wareArea = await _wareAreaRep.DetachedEntities.Where(z => z.Id == input.AreaId).FirstOrDefaultAsync();
            if (wareArea == null) throw Oops.Oh("所属库区信息不存在!");
            if (input.WareContainerVsMaterials.Count == 0) throw Oops.Oh("无入库物料信息");

            //判断是否为虚拟库区  南京,一楼停车厂,一号车间
            if (wareArea.AreaType == AreaTypeEnum.XN)
            {
                //查询一条空闲的库位信息
                var wareLocation = await _wareLocationRep.Where(z => z.AreaID == input.AreaId && z.LocationStatus == LocationStatusEnum.kongxian).FirstOrDefaultAsync();
                if (wareLocation == null) throw Oops.Oh("该库区暂无空闲库位");
                //查询一条空闲的容器信息
                var wareContainer = await _wareContainerRep.Where(z => z.AreaID == input.AreaId && z.ContainerStatus == ContainerStatusEnum.kongxian).FirstOrDefaultAsync();
                if (wareContainer == null) throw Oops.Oh("该库区暂无空闲容器");
                //组盘单据
                var orderNo = YitIdHelper.NextId().ToString();
                //进行组盘
                foreach (var itemsub in input.WareContainerVsMaterials)
                {
                    if (itemsub.BindQuantity <= 0) continue;
                    var model = itemsub.Adapt<WareContainerVsMaterial>();
                    model.Id = YitIdHelper.NextId();
                    model.ProjectCode = String.IsNullOrEmpty(itemsub.ProjectCode) ? "N/A" : itemsub.ProjectCode;
                    model.OrderNo = orderNo;
                    model.ContainerCode = wareContainer.Code;
                    model.ContainerId = wareContainer.Id;
                    model.ContainerVsMaterialStatus = CommonStatus.ENABLE;
                    model.ExpirationTime = itemsub.ExpirationTime;
                    await _wareContainerVsMaterialRep.InsertAsync(model);

                    //更新库存
                    var stockDetailModel = await _wareStockRep.FirstOrDefaultAsync(n => n.ContainerCode == wareContainer.Code
                    && n.ProjectCode == itemsub.ProjectCode && n.Code == itemsub.Code && n.SpecificationModel == itemsub.SpecificationModel);
                    if (stockDetailModel != null)
                    {
                        stockDetailModel.StockQuantity += itemsub.BindQuantity;
                        stockDetailModel.ProjectCode = itemsub.ProjectCode;
                        stockDetailModel.ExpirationTime = itemsub.ExpirationTime;
                        await _wareStockRep.UpdateAsync(stockDetailModel);
                    }
                    else
                    {
                        stockDetailModel = new WareStock()
                        {
                            ProjectCode = itemsub.ProjectCode,
                            Code = itemsub.Code,
                            Name = itemsub.Name,
                            SpecificationModel = itemsub.SpecificationModel,
                            Unit = itemsub.Unit,
                            StockQuantity = itemsub.BindQuantity,
                            CurrentQuantity = itemsub.BindQuantity,
                            ContainerCode = wareContainer.Code,
                            LocationCode = wareLocation.Code,
                            XuHao = itemsub.XuHao,
                            BrandName = itemsub.BrandName,
                            ExpirationTime = itemsub.ExpirationTime,
                            CreatedUserId = CurrentUserInfo.UserId,
                            CreatedUserName = CurrentUserInfo.Name,
                            CreatedTime = DateTimeOffset.Now,
                            UpdatedUserId = CurrentUserInfo.UserId,
                            UpdatedUserName = CurrentUserInfo.Name,
                            UpdatedTime = DateTimeOffset.Now
                        };
                        await _wareStockRep.InsertAsync(stockDetailModel);
                    }
                    if (!string.IsNullOrEmpty(itemsub.DeliveryNo) && itemsub.DeliveryNo != "N/A")
                    {
                        //更新收货数据入库数量  -- deliveryNo 没有传递
                        var collectDate = await _collectDeliveryDetailsRep.Where(n => n.Code == itemsub.Code).ToListAsync();
                        foreach (var item in collectDate)
                        {
                            var hegeQuatity = new decimal(1.00); // 定义合格数
                            // 物料检验方式是免检，直接显示收货数量
                            if (item.InspectionMethod == InspectionMethodEnum.mianjian)
                                hegeQuatity = item.CollectQuantity;
                            // 质检后质检结果是合格或者让步接收，合格数直接显示质检数量
                            else if (item.IsQuality == YesOrNot.Y && item.QualityResult == QualityEnum.HeGe || item.QualityResult == QualityEnum.RangBu)
                                hegeQuatity = item.CollectQuantity;//合格数量
                            else
                                hegeQuatity = item.CollectQuantity - item.QualityNumber; //合格数量

                            if (itemsub.BindQuantity <= hegeQuatity)
                            {
                                item.WarehousingQuantity = itemsub.BindQuantity;
                                await _collectDeliveryDetailsRep.UpdateAsync(collectDate);
                                break;
                            }
                            if (itemsub.BindQuantity > hegeQuatity)
                            {
                                item.WarehousingQuantity = itemsub.BindQuantity - hegeQuatity;
                                await _collectDeliveryDetailsRep.UpdateAsync(collectDate);
                                itemsub.BindQuantity -= hegeQuatity;

                            }
                        }
                    }
                }

                //新增库位容器关系表
                var newWareLocationVsContainerModel = new WareLocationVsContainer()
                {
                    LocationId = wareLocation.Id,
                    LocationCode = wareLocation.Code,
                    ContainerId = wareContainer.Id,
                    ContainerCode = wareContainer.Code,
                    LocationVsContainerStatus = CommonStatus.ENABLE
                };
                await _wareLocationVsContainerRep.InsertAsync(newWareLocationVsContainerModel);

                //更新库位状态
                wareLocation.LocationStatus = LocationStatusEnum.cunhuo;
                await _wareLocationRep.UpdateAsync(wareLocation);

                //更新容器状态
                wareContainer.ContainerStatus = ContainerStatusEnum.kuwei;
                await _wareContainerRep.UpdateAsync(wareContainer);

                //创建任务
                var taskModel = new WareTask()
                {
                    OrderNo = orderNo,
                    TaskNo = YitIdHelper.NextId().ToString(),
                    TaskStatus = TaskStatusEnum.Complete,
                    TaskModel = TaskModel.SHOUDONG,
                    TaskType = TaskType.In,
                    TaskName = TaskNameConst.TemporaryLocation_ManualIn,
                    Priority = 1,
                    ContainerCode = wareContainer.Code,
                    FromLocationCode = "入库口", //入库口
                    ToLocationCode = wareLocation.Code,
                    CreatedUserId = CurrentUserInfo.UserId,
                    CreatedUserName = CurrentUserInfo.Name,
                    CreatedTime = DateTimeOffset.Now,
                    UpdatedUserId = CurrentUserInfo.UserId,
                    UpdatedUserName = CurrentUserInfo.Name,
                    UpdatedTime = DateTimeOffset.Now
                };
                await _wareTaskRep.InsertAsync(taskModel);
            }
            else
            {
                // 根据库位编号查询库区ID
                var wareLocation = await _wareLocationRep.FirstOrDefaultAsync(z => z.Code == input.LocationCode);
                if (wareLocation == null) throw Oops.Oh(errorMessage: "库位不存在!");
                if (wareLocation.IsLock == YesOrNot.Y) throw Oops.Oh("库位被锁定!");

                //删除存在的信息
                var locationVsContainer = await _wareLocationVsContainerRep.FirstOrDefaultAsync(p => p.LocationCode == input.LocationCode && p.LocationVsContainerStatus == CommonStatus.ENABLE);
                if (locationVsContainer != null)
                {
                    //组盘关系删除
                    var odvs = await _wareContainerVsMaterialRep.Where(p => p.ContainerCode == locationVsContainer.ContainerCode && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();
                    foreach (var item in odvs)
                    {
                        item.ContainerVsMaterialStatus = CommonStatus.DELETED;
                    }
                    await _wareContainerVsMaterialRep.UpdateAsync(odvs);
                    //容器空闲
                    var containermodel = await _wareContainerRep.Where(z => z.AreaID == input.AreaId && z.Code == locationVsContainer.ContainerCode).FirstOrDefaultAsync();
                    if (containermodel != null)
                    {
                        containermodel.ContainerStatus = ContainerStatusEnum.kongxian;
                        await _wareContainerRep.UpdateAsync(containermodel);
                    }
                    //对应的库存清空
                    var stockList = await _wareStockRep.Where(p => p.LocationCode == wareLocation.Code).ToListAsync();
                    await _wareStockRep.DeleteAsync(stockList);

                    locationVsContainer.LocationVsContainerStatus = CommonStatus.DELETED;
                    await _wareLocationVsContainerRep.UpdateAsync(locationVsContainer);
                }

                //组盘单据
                var orderNo = YitIdHelper.NextId().ToString();
                //查询一条空闲的容器信息
                var container = await _wareContainerRep.Where(z => z.AreaID == input.AreaId && z.ContainerStatus == ContainerStatusEnum.kongxian).FirstOrDefaultAsync();
                if (container == null) throw Oops.Oh("该库区暂无空闲容器");
                //进行组盘
                foreach (var itemsub in input.WareContainerVsMaterials)
                {
                    var model = itemsub.Adapt<WareContainerVsMaterial>();
                    model.Id = YitIdHelper.NextId();
                    model.ProjectCode = String.IsNullOrEmpty(itemsub.ProjectCode) ? "N/A" : itemsub.ProjectCode;
                    model.OrderNo = orderNo;
                    model.ContainerCode = container.Code;
                    model.ContainerId = container.Id;
                    model.ContainerVsMaterialStatus = CommonStatus.ENABLE;
                    model.ExpirationTime = itemsub.ExpirationTime;
                    await _wareContainerVsMaterialRep.InsertAsync(model);

                    //更新库存
                    var stockDetailModel = await _wareStockRep.FirstOrDefaultAsync(n => n.ContainerCode == container.Code
                    && n.ProjectCode == itemsub.ProjectCode && n.Code == itemsub.Code && n.SpecificationModel == itemsub.SpecificationModel);
                    if (stockDetailModel != null)
                    {
                        stockDetailModel.StockQuantity += itemsub.BindQuantity;
                        stockDetailModel.ProjectCode = itemsub.ProjectCode;
                        stockDetailModel.ExpirationTime = itemsub.ExpirationTime;
                        await _wareStockRep.UpdateAsync(stockDetailModel);
                    }
                    else
                    {
                        stockDetailModel = new WareStock()
                        {
                            ProjectCode = itemsub.ProjectCode,
                            Code = itemsub.Code,
                            Name = itemsub.Name,
                            SpecificationModel = itemsub.SpecificationModel,
                            Unit = itemsub.Unit,
                            StockQuantity = itemsub.BindQuantity,
                            CurrentQuantity = itemsub.BindQuantity,
                            ContainerCode = container.Code,
                            LocationCode = input.LocationCode,
                            XuHao = itemsub.XuHao,
                            BrandName = itemsub.BrandName,
                            ExpirationTime = itemsub.ExpirationTime,
                            CreatedUserId = CurrentUserInfo.UserId,
                            CreatedUserName = CurrentUserInfo.Name,
                            CreatedTime = DateTimeOffset.Now,
                            UpdatedUserId = CurrentUserInfo.UserId,
                            UpdatedUserName = CurrentUserInfo.Name,
                            UpdatedTime = DateTimeOffset.Now
                        };
                        await _wareStockRep.InsertAsync(stockDetailModel);
                    }
                    if (!string.IsNullOrEmpty(itemsub.DeliveryNo) && itemsub.DeliveryNo != "N/A")
                    {
                        //更新收货数据入库数量  -- deliveryNo 没有传递
                        var collectDate = await _collectDeliveryDetailsRep.Where(n => n.Code == itemsub.Code).ToListAsync();
                        foreach (var item in collectDate)
                        {
                            var hegeQuatity = new decimal(1.00); // 定义合格数
                            // 物料检验方式是免检，直接显示收货数量
                            if (item.InspectionMethod == InspectionMethodEnum.mianjian)
                                hegeQuatity = item.CollectQuantity;
                            // 质检后质检结果是合格或者让步接收，合格数直接显示质检数量
                            else if (item.IsQuality == YesOrNot.Y && item.QualityResult == QualityEnum.HeGe || item.QualityResult == QualityEnum.RangBu)
                                hegeQuatity = item.CollectQuantity;//合格数量
                            else
                                hegeQuatity = item.CollectQuantity - item.QualityNumber; //合格数量

                            if (itemsub.BindQuantity <= hegeQuatity)
                            {
                                item.WarehousingQuantity = itemsub.BindQuantity;
                                await _collectDeliveryDetailsRep.UpdateAsync(collectDate);
                                break;
                            }
                            if (itemsub.BindQuantity > hegeQuatity)
                            {
                                item.WarehousingQuantity = itemsub.BindQuantity - hegeQuatity;
                                await _collectDeliveryDetailsRep.UpdateAsync(collectDate);
                                itemsub.BindQuantity -= hegeQuatity;

                            }
                        }
                    }
                }
                //新增库位容器关系表
                var newWareLocationVsContainerModel = new WareLocationVsContainer()
                {
                    LocationId = wareLocation.Id,
                    LocationCode = input.LocationCode,
                    ContainerId = container.Id,
                    ContainerCode = container.Code,
                    LocationVsContainerStatus = CommonStatus.ENABLE
                };
                await _wareLocationVsContainerRep.InsertAsync(newWareLocationVsContainerModel);
                //更新新库位
                wareLocation.LocationStatus = LocationStatusEnum.cunhuo;
                await _wareLocationRep.UpdateAsync(wareLocation);
                //更容器信息
                container.ContainerStatus = ContainerStatusEnum.kuwei;
                await _wareContainerRep.UpdateAsync(container);

                //创建任务
                var taskModel = new WareTask()
                {
                    OrderNo = orderNo,
                    TaskNo = YitIdHelper.NextId().ToString(),
                    TaskStatus = TaskStatusEnum.Complete,
                    TaskModel = TaskModel.SHOUDONG,
                    TaskType = TaskType.In,
                    TaskName = TaskNameConst.NotContainer_ManualIn,
                    Priority = 1,
                    ContainerCode = container.Code,
                    FromLocationCode = "N/A", //入库口
                    ToLocationCode = input.LocationCode,
                    CreatedUserId = CurrentUserInfo.UserId,
                    CreatedUserName = CurrentUserInfo.Name,
                    CreatedTime = DateTimeOffset.Now,
                    UpdatedUserId = CurrentUserInfo.UserId,
                    UpdatedUserName = CurrentUserInfo.Name,
                    UpdatedTime = DateTimeOffset.Now,
                    Images = input.Images != null && input.Images.Count > 0 ? string.Join(",", input.Images) : "N/A"
                };
                await _wareTaskRep.InsertAsync(taskModel);
            }

        }
        #endregion

        /// <summary>
        /// 查询agv入库口
        /// </summary>
        /// <returns></returns>
        [HttpGet("WareAgvList")]
        public async Task<List<AgvLocationOutput>> WareAgvList()
        {
            return await _wareLocationRep
                .Where(t => t.LocationStatus == LocationStatusEnum.kongxian && t.AreaID == 425780734464069)
                .ProjectToType<AgvLocationOutput>().ToListAsync();
        }

        /// <summary>
        /// 托盘变更
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("ChangeNewContainer")]
        public async Task GetContainerByMaterialReturn([FromBody] ChangeContainerInput input)
        {
            //检查老的托盘
            var oldwareContainer = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == input.OldContainerCode);
            if (oldwareContainer == null) throw Oops.Oh("容器信息不存在!");
            if (oldwareContainer.ContainerStatus == ContainerStatusEnum.jinyong) throw Oops.Oh("容器已禁用!");
            if (oldwareContainer.ContainerStatus != ContainerStatusEnum.zupan) throw Oops.Oh("容器不在组盘中!");
            //判断是否在任务中
            var isExit = await _wareTaskRep.AnyAsync(n => n.TaskStatus != TaskStatusEnum.Complete && n.ContainerCode == input.OldContainerCode);
            if (isExit) throw Oops.Oh("容器存在未完成任务!");
            //判断是否分拣完成
            var wareSortOrderCount = await _wareSortOrderRep.DetachedEntities
               .Where(p => p.ContainerCode == input.OldContainerCode && p.SortStatus != SortStatusEnum.Completed).CountAsync();
            if (wareSortOrderCount > 0) throw Oops.Oh("容器存在未分拣物料!");

            //检查新托盘
            var newwareContainer = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == input.NewContainerCode);

            if (newwareContainer == null)
            {
                newwareContainer = new WareContainer()
                {
                    Code = input.NewContainerCode,
                    IsVirtual = YesOrNot.N,
                    ContainerStatus = ContainerStatusEnum.kongxian,
                    Id = YitIdHelper.NextId(),
                    AreaID = oldwareContainer.AreaID
                };
                await _wareContainerRep.InsertAsync(newwareContainer);
            }
            if (newwareContainer.ContainerStatus != ContainerStatusEnum.kongxian)
                throw Oops.Oh("容器非空闲!不可用");

            //改变老的托盘的状态
            oldwareContainer.ContainerStatus = ContainerStatusEnum.kongxian;
            //修改托盘状态
            newwareContainer.ContainerStatus = ContainerStatusEnum.zupan;

            //禁用老托盘物料容器关系表
            var WareContainerVsMaterials = await _wareContainerVsMaterialRep
                .Where(p => p.WareContainer.Code == input.OldContainerCode && p.ContainerVsMaterialStatus == CommonStatus.ENABLE)
                .ToListAsync();
            foreach (var item in WareContainerVsMaterials)
            {
                item.ContainerVsMaterialStatus = CommonStatus.DELETED;
            }
            //构建新的组盘记录
            var OrderNo = YitIdHelper.NextId().ToString();
            foreach (var itemsub in input.WareContainerVsMaterials)
            {
                var item = itemsub.Adapt<WareContainerVsMaterial>();
                item.Id = YitIdHelper.NextId();
                item.OrderNo = OrderNo;
                item.ContainerId = newwareContainer.Id;
                item.ContainerCode = newwareContainer.Code;
                itemsub.ContainerVsMaterialStatus = CommonStatus.ENABLE;
                await _wareContainerVsMaterialRep.InsertAsync(item);
            }
        }

        /// <summary>
        /// 组盘操作
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("GroupContainer")]
        [UnitOfWork]
        public async Task GroupContainer([FromBody] ContainerOutput input)
        {
            if (input.WareContainer == null) throw Oops.Oh(errorMessage: "请扫描容器！");
            if (input.WareContainerVsMaterials.Count == 0) throw Oops.Oh(errorMessage: "请扫描物料信息！");

            //检查托盘
            var wareContainer = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == input.WareContainer.Code);
            if (wareContainer == null) throw Oops.Oh("容器信息不存在!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.jinyong) throw Oops.Oh("容器已禁用!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.kuwei) throw Oops.Oh("容器在库位不可使用!");

            //判断是否在任务中
            var isExit = await _wareTaskRep.AnyAsync(n => n.TaskStatus != TaskStatusEnum.Complete
                 && n.ContainerCode == input.WareContainer.Code);
            if (isExit) throw Oops.Oh("容器存在未完成任务!");

            //删除原来组盘记录
            var WareContainerVsMaterials = await _wareContainerVsMaterialRep.DetachedEntities
            .Where(p => p.WareContainer.Code == input.WareContainer.Code
            && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();
            foreach (var itemsub in WareContainerVsMaterials)
            {
                await _wareContainerVsMaterialRep.DeleteAsync(itemsub);
            }

            //构建新的组盘记录
            var OrderNo = YitIdHelper.NextId().ToString();
            foreach (var itemsub in input.WareContainerVsMaterials)
            {
                var item = itemsub.Adapt<WareContainerVsMaterial>();
                item.Id = YitIdHelper.NextId();
                item.OrderNo = OrderNo;
                item.ProjectCode = String.IsNullOrEmpty(itemsub.ProjectCode) ? "N/A" : itemsub.ProjectCode;
                item.ContainerId = wareContainer.Id;
                item.ContainerCode = wareContainer.Code;
                item.ExpirationTime = itemsub.ExpirationTime;
                item.CreatedUserId = CurrentUserInfo.UserId;
                item.CreatedUserName = CurrentUserInfo.Name;
                item.CreatedTime = DateTimeOffset.Now;
                item.ContainerVsMaterialStatus = CommonStatus.ENABLE;
                await _wareContainerVsMaterialRep.InsertAsync(item);
                if (!string.IsNullOrEmpty(itemsub.DeliveryNo) && itemsub.DeliveryNo != "N/A")
                {
                    //更新收货数据入库数量  -- deliveryNo 没有传递
                    var collectDate = await _collectDeliveryDetailsRep.Where(n => n.Code == itemsub.Code).ToListAsync();
                    foreach (var collectModel in collectDate)
                    {
                        var hegeQuatity = new decimal(1.00); // 定义合格数
                                                             // 物料检验方式是免检，直接显示收货数量
                        if (item.InspectionMethod == InspectionMethodEnum.mianjian)
                            hegeQuatity = collectModel.CollectQuantity;
                        // 质检后质检结果是合格或者让步接收，合格数直接显示质检数量
                        else if (collectModel.IsQuality == YesOrNot.Y && collectModel.QualityResult == QualityEnum.HeGe || collectModel.QualityResult == QualityEnum.RangBu)
                            hegeQuatity = collectModel.CollectQuantity;//合格数量
                        else
                            hegeQuatity = collectModel.CollectQuantity - collectModel.QualityNumber; //合格数量

                        if (itemsub.BindQuantity <= hegeQuatity)
                        {
                            collectModel.WarehousingQuantity = itemsub.BindQuantity;
                            await _collectDeliveryDetailsRep.UpdateAsync(collectDate);
                            break;
                        }
                        if (itemsub.BindQuantity > hegeQuatity)
                        {
                            collectModel.WarehousingQuantity = itemsub.BindQuantity - hegeQuatity;
                            await _collectDeliveryDetailsRep.UpdateAsync(collectDate);
                            itemsub.BindQuantity -= hegeQuatity;

                        }
                    }
                }
            }
            //修改托盘状态
            wareContainer.ContainerStatus = ContainerStatusEnum.zupan;
            await _wareContainerRep.UpdateAsync(wareContainer);
        }

        /// <summary>
        /// 解绑操作
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("UnBindContainer")]
        [UnitOfWork]
        public async Task UnBindContainer([FromBody] ContainerInput input)
        {
            if (string.IsNullOrEmpty(input.ContainerCode)) throw Oops.Oh(errorMessage: "请扫描容器！");

            //检查托盘
            var wareContainer = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == input.ContainerCode);
            if (wareContainer == null) throw Oops.Oh("容器信息不存在!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.jinyong) throw Oops.Oh("容器已禁用!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.kuwei) throw Oops.Oh("容器在库位不可使用!");

            //判断是否在任务中
            var isExit = await _wareTaskRep.AnyAsync(n => n.TaskStatus != TaskStatusEnum.Complete && n.ContainerCode == input.ContainerCode);
            if (isExit) throw Oops.Oh("容器存在未完成任务!");

            //删除组盘记录
            var WareContainerVsMaterials = await _wareContainerVsMaterialRep.DetachedEntities
               .Where(p => p.WareContainer.Code == input.ContainerCode
                && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();
            foreach (var itemsub in WareContainerVsMaterials)
            {
                await _wareContainerVsMaterialRep.DeleteAsync(itemsub);
            }

            //修改托盘状态
            wareContainer.ContainerStatus = ContainerStatusEnum.kongxian;
            await _wareContainerRep.UpdateAsync(wareContainer);
        }

        /// <summary>
        /// 余料回库
        /// </summary>
        /// <returns></returns>
        [HttpPost("MaterialReturn")]
        [UnitOfWork]
        public async Task MaterialReturn(WarehousingInput input)
        {
            //检查托盘
            var wareContainer = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == input.WareContainer.Code);
            if (wareContainer == null) throw Oops.Oh("容器信息不存在!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.jinyong) throw Oops.Oh("容器已禁用!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.kuwei) throw Oops.Oh("容器已入库!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.fenjian) throw Oops.Oh("容器存在分拣单据!");
            //判断是否在任务中
            var isExit = await _wareTaskRep.AnyAsync(n => n.TaskStatus != TaskStatusEnum.Complete && n.ContainerCode == input.WareContainer.Code);
            if (isExit) throw Oops.Oh("容器存在未完成任务!");

            //5.修改agv分拣库位信息
            var LontionVSContion = await _wareLocationVsContainerRep.FirstOrDefaultAsync(z => z.ContainerCode == wareContainer.Code &&
            z.LocationVsContainerStatus == CommonStatus.ENABLE && z.LocationCode.StartsWith("Location"));
            if(LontionVSContion == null) throw Oops.Oh("AGV分拣库位关系不存在!");
            var agvLocation = await _wareLocationRep.FirstOrDefaultAsync(z => z.Code == LontionVSContion.LocationCode);
            if (agvLocation == null) throw Oops.Oh("AGV分拣库位不存在!");
            agvLocation.LocationStatus = LocationStatusEnum.daichu;
            if (input.TaskModel == TaskModel.SHOUDONG)
            {
                await _wareLocationVsContainerRep.DeleteAsync(LontionVSContion);
                agvLocation.LocationStatus = LocationStatusEnum.kongxian;
            }
            await _wareLocationRep.UpdateAsync(agvLocation);

            //组盘
            //1.定义单据号,区分是空托盘入库还是物料入库
            var orderNo = "N/A";
            if (input.WareContainerVsMaterials.Count > 0) orderNo = YitIdHelper.NextId().ToString();
            //3.获取组盘记录
            var wareContainerVsMaterialList = await _wareContainerVsMaterialRep.DetachedEntities.Where(p => p.ContainerCode == wareContainer.Code
                && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();

            //4.满足条件进行组盘
            if (input.WareContainerVsMaterials.Count > 0)
            {
                foreach (var itemsub in wareContainerVsMaterialList)
                {
                    await _wareContainerVsMaterialRep.DeleteAsync(itemsub);
                }
                foreach (var itemsub in input.WareContainerVsMaterials)
                {
                    if (itemsub.BindQuantity <= 0) continue;
                    var model = itemsub.Adapt<WareContainerVsMaterial>();
                    model.Id = YitIdHelper.NextId();
                    model.ProjectCode = itemsub.ProjectCode;
                    model.OrderNo = orderNo;
                    model.ContainerCode = wareContainer.Code;
                    model.ContainerId = wareContainer.Id;
                    model.ExpirationTime = itemsub.ExpirationTime;
                    model.ContainerVsMaterialStatus = CommonStatus.ENABLE;
                    await _wareContainerVsMaterialRep.InsertAsync(model);
                }
            }

            var taskNo = YitIdHelper.NextId().ToString();

            if (wareContainer.Code.StartsWith("TJ"))//立体库
            {
                if (input.TaskModel == TaskModel.SHOUDONG) //手动入库
                {
                    //1.创建任务
                    var taskModel = new WareTask()
                    {
                        OrderNo = orderNo,
                        TaskNo = YitIdHelper.NextId().ToString(),
                        TaskType = TaskType.In,
                        TaskModel = TaskModel.SHOUDONG,
                        TaskName = orderNo == "N/A" ? TaskNameConst.KongTuo_LitikuManualIn : TaskNameConst.Litiku_ManualIn,
                        TaskStatus = TaskStatusEnum.NotProgress,
                        Priority = 2,
                        ContainerCode = wareContainer.Code,
                        FromLocationCode = "N/A",
                        ToLocationCode = "N/A",
                        CreatedUserId = CurrentUserInfo.UserId,
                        CreatedUserName = CurrentUserInfo.Name,
                        IsRead = true,
                        Images = input.Images != null && input.Images.Count > 0 ? string.Join(",", input.Images) : "N/A",
                    };
                    await _wareTaskRep.InsertAsync(taskModel);
                }
                else  //自动入库
                {
                    // 调用AGV服务创建指定名称的订单
                    var createTransportOrders = new CreateTransportOrdersInput();
                    createTransportOrders.TaskNo = taskNo;
                    createTransportOrders.intendedVehicle = "Vehicle-0001"; //立体库执行车辆
                    var destList = new List<DestinationsInput>();
                    var dest1 = new DestinationsInput()
                    {
                        locationName = agvLocation.Code, //地面站点/上料口
                        operation = "Load cargo:12" //地面层数是12，Load是取货
                    };
                    var dest2 = new DestinationsInput()
                    {
                        locationName = "Location-0016", //[Location-0016]入库对应的输送线
                        operation = "Unload cargo:01" //输送线层数是1，Unload是放货
                    };
                    destList.Add(dest1);
                    destList.Add(dest2);
                    createTransportOrders.destinations = destList;

                    var createTransportOrdersOutput = await _agvService.CreateTransportOrders(createTransportOrders);
                    // 写日志文件
                    Log.Error($"[LitikuIn][createTransportOrdersOutput:{createTransportOrdersOutput.ToJson()}]");

                    if (createTransportOrdersOutput.result == "success")
                    {
                        // 创建AGV入库任务
                        var wareAgvTask = new WareAgvTask()
                        {
                            TaskType = "入库",
                            StartPlace = agvLocation.Code, //地面站点/上料口
                            EndPlace = "Location-0016", //[Location-0016]入库对应的输送线
                            TransportOrder = taskNo,
                            AgvState = "TRAVELLING",
                            ContainerCode = input.WareContainer.Code,
                        };
                        await _wareAgvTaskRep.InsertAsync(wareAgvTask);

                        //1.创建任务
                        var taskModel = new WareTask()
                        {
                            OrderNo = orderNo,
                            TaskNo = taskNo,
                            TaskType = TaskType.In,
                            TaskModel = TaskModel.ZIDONG,
                            TaskName = orderNo == "N/A" ? TaskNameConst.KongTuo_LitikuManualIn : TaskNameConst.Litiku_ManualIn,
                            TaskStatus = TaskStatusEnum.NotProgress,
                            Priority = 2,
                            ContainerCode = wareContainer.Code,
                            FromLocationCode = agvLocation.Code,
                            ToLocationCode = "N/A",
                            CreatedUserId = CurrentUserInfo.UserId,
                            CreatedUserName = CurrentUserInfo.Name,
                            IsRead = false,
                            Images = input.Images != null && input.Images.Count > 0 ? string.Join(",", input.Images) : "N/A",
                        };
                        await _wareTaskRep.InsertAsync(taskModel);
                    }
                }

            }
            else //平库
            {
                if (input.TaskModel == TaskModel.SHOUDONG) //手动入库
                {
                    //检查库位
                    var locationModel = await _wareLocationRep.FirstOrDefaultAsync(p => p.AreaID == input.AreaId
                    && p.Code == input.LocationCode);
                    if (locationModel == null) throw Oops.Oh("库位不存在!");
                    if (locationModel.LocationStatus != LocationStatusEnum.kongxian) throw Oops.Oh("库位被占用!");
                    if (locationModel.IsLock == YesOrNot.Y) throw Oops.Oh("库位被锁定!");

                    //修改托盘状态
                    wareContainer.ContainerStatus = ContainerStatusEnum.kuwei;
                    await _wareContainerRep.UpdateAsync(wareContainer);

                    //更新库位
                    locationModel.LocationStatus = LocationStatusEnum.cunhuo;
                    if (orderNo == "N/A") locationModel.IsEmptyContainer = YesOrNot.Y;
                    else locationModel.IsEmptyContainer = YesOrNot.N;
                    await _wareLocationRep.UpdateAsync(locationModel);

                    //构建容器与库位关系表
                    var wareLocationVsContainerModel = new WareLocationVsContainer()
                    {
                        LocationId = locationModel.Id,
                        LocationCode = locationModel.Code,
                        ContainerId = wareContainer.Id,
                        ContainerCode = wareContainer.Code,
                        LocationVsContainerStatus = CommonStatus.ENABLE
                    };
                    await _wareLocationVsContainerRep.InsertAsync(wareLocationVsContainerModel);

                    foreach (var itemsub in input.WareContainerVsMaterials)
                    {
                        //更新库存
                        var stockDetailModel = await _wareStockRep.FirstOrDefaultAsync(n => n.ContainerCode == itemsub.ContainerCode
                        && n.ProjectCode == itemsub.ProjectCode && n.Code == itemsub.Code && n.SpecificationModel == itemsub.SpecificationModel);

                        if (stockDetailModel != null)
                        {
                            stockDetailModel.StockQuantity = itemsub.BindQuantity;
                            stockDetailModel.LocationCode = locationModel.Code;
                            stockDetailModel.CurrentQuantity = itemsub.BindQuantity;
                            await _wareStockRep.UpdateAsync(stockDetailModel);
                        }
                        else
                        {
                            stockDetailModel = new WareStock()
                            {
                                ProjectCode = itemsub.ProjectCode,
                                Code = itemsub.Code,
                                Name = itemsub.Name,
                                SpecificationModel = itemsub.SpecificationModel,
                                Unit = itemsub.Unit,
                                StockQuantity = itemsub.BindQuantity,
                                CurrentQuantity = itemsub.BindQuantity,
                                ContainerCode = wareContainer.Code,
                                LocationCode = locationModel.Code,
                                XuHao = itemsub.XuHao,
                                BrandName = itemsub.BrandName,
                                ExpirationTime = DateTimeOffset.Now,
                                CreatedUserId = CurrentUserInfo.UserId,
                                CreatedUserName = CurrentUserInfo.Name,
                                CreatedTime = DateTimeOffset.Now,
                                UpdatedUserId = CurrentUserInfo.UserId,
                                UpdatedUserName = CurrentUserInfo.Name,
                                UpdatedTime = DateTimeOffset.Now
                            };
                            await _wareStockRep.InsertNowAsync(stockDetailModel);
                        }

                        if (!string.IsNullOrEmpty(itemsub.DeliveryNo) && itemsub.DeliveryNo != "N/A")
                        {
                            //更新收货数据入库数量  -- deliveryNo 没有传递
                            var model = await _collectDeliveryDetailsRep.FirstOrDefaultAsync(n => n.ProjectCode == itemsub.ProjectCode
                                 && n.Code == itemsub.Code && n.CollectDelivery.DeliveryNo == itemsub.DeliveryNo);
                            if (model != null)
                            {
                                model.WarehousingQuantity += itemsub.BindQuantity;
                                await _collectDeliveryDetailsRep.UpdateAsync(model);
                            }
                        }
                    }

                    //空托
                    if (orderNo == "N/A")
                    {
                        var stockModel = new WareStock()
                        {
                            ProjectCode = "N/A",
                            Code = "N/A",
                            Name = "N/A",
                            SpecificationModel = "N/A",
                            Unit = "N/A",
                            StockQuantity = 1,
                            CurrentQuantity = 1,
                            ContainerCode = wareContainer.Code,
                            LocationCode = locationModel.Code,
                            XuHao = "N/A",
                            BrandName = "",
                            UpdatedUserId = CurrentUserInfo.UserId,
                            UpdatedUserName = CurrentUserInfo.Name,
                            UpdatedTime = DateTimeOffset.Now
                        };
                        await _wareStockRep.InsertAsync(stockModel);
                    }

                    //1.创建任务
                    var taskModel = new WareTask()
                    {
                        OrderNo = orderNo,
                        TaskNo = YitIdHelper.NextId().ToString(),
                        TaskType = TaskType.In,
                        TaskModel = TaskModel.SHOUDONG,
                        TaskName = orderNo == "N/A" ? TaskNameConst.KongTuo_PingkuManualIn : TaskNameConst.Pingku_ManualIn,
                        TaskStatus = TaskStatusEnum.Complete,
                        Priority = 1,
                        ContainerCode = wareContainer.Code,
                        ToLocationCode = input.LocationCode,
                        FromLocationCode = "N/A",
                        CreatedUserId = CurrentUserInfo.UserId,
                        CreatedUserName = CurrentUserInfo.Name,
                        CreatedTime = DateTime.Now,
                        UpdatedUserId = CurrentUserInfo.UserId,
                        UpdatedUserName = CurrentUserInfo.Name,
                        UpdatedTime = DateTime.Now,
                        Images = input.Images != null && input.Images.Count > 0 ? string.Join(",", input.Images) : "N/A",
                    };
                    await _wareTaskRep.InsertAsync(taskModel);
                }
                else if (input.TaskModel == TaskModel.ZIDONG) //自动入库
                {
                    #region 创建任务
                    //1.创建任务
                    var taskModel = new WareTask()
                    {
                        OrderNo = orderNo,
                        TaskNo = taskNo,
                        TaskType = TaskType.In,
                        TaskModel = TaskModel.ZIDONG,
                        TaskName = orderNo == "N/A" ? TaskNameConst.KongTuo_PingkuAutomaticIn : TaskNameConst.Pingku_AutomaticIn,
                        TaskStatus = TaskStatusEnum.NotProgress,
                        Priority = 1,
                        IsRead = false,
                        ContainerCode = wareContainer.Code,
                        FromLocationCode = agvLocation.Code, //入口
                        ToLocationCode = "N/A",
                        CreatedUserId = CurrentUserInfo.UserId,
                        CreatedUserName = CurrentUserInfo.Name,
                        CreatedTime = DateTimeOffset.Now,
                        UpdatedUserId = CurrentUserInfo.UserId,
                        UpdatedUserName = CurrentUserInfo.Name,
                        UpdatedTime = DateTimeOffset.Now,
                        Images = input.Images != null && input.Images.Count > 0 ? string.Join(",", input.Images) : "N/A"
                    };
                    if (!string.IsNullOrEmpty(input.LocationCode))
                    {
                        var locationModel = await _wareLocationRep.FirstOrDefaultAsync(p => p.Code == input.LocationCode && p.IsLock == YesOrNot.N && p.LocationStatus == LocationStatusEnum.kongxian);
                        if (locationModel == null) throw Oops.Oh("库位不存在或不能使用!");

                        taskModel.ToLocationCode = input.LocationCode;
                    }
                    await _wareTaskRep.InsertAsync(taskModel);

                    #endregion

                    #region 创建AGV任务
                    // 调用AGV服务创建指定名称的订单 第一段任务
                    var agvModel = new CreateOrdersedInput()
                    {
                        TaskNo = taskNo + "-1",
                        locationName = agvLocation.Code,
                        operation = "Load cargo:12"
                    };
                    var createTransportOrdersOutput = await _agvService.CreateLoadOrders(agvModel);

                    if (createTransportOrdersOutput.result == "success")
                    {
                        // 创建AGV入库任务
                        var wareAgvTask = new WareAgvTask()
                        {
                            TaskType = "入库",
                            StartPlace = agvLocation.Code, //地面站点/上料口
                            EndPlace = "9067", //平库原库位编号
                            TransportOrder = taskNo,
                            AgvState = "PRISTINE",
                            ContainerCode = input.WareContainer.Code
                        };
                        await _wareAgvTaskRep.InsertAsync(wareAgvTask);
                    }
                    #endregion
                }
            }


        }

        #region 呼叫AGV
        /// <summary>
        /// 查询Agv库位信息
        /// </summary>
        /// <returns></returns>
        [HttpPost("AgvLocation")]
        public async Task<List<WareLocation>> AgvLocation()
        {
            return await _wareLocationRep.Where(z => z.AreaID == 410594643796037).ToListAsync();
        }

        /// <summary>
        /// 呼叫Agv操作
        /// </summary>
        /// <returns></returns>
        [HttpPost("CallAgvMovement")]
        public async Task CallAgvMovement(CallsAgvInput input)
        {
            //查询起始点库位信息
            var StartLocation = await _wareLocationRep.Where(z => z.Code == input.StartCode && z.LocationStatus == LocationStatusEnum.cunhuo).FirstOrDefaultAsync();
            if (StartLocation == null) throw Oops.Oh("无起始点库位信息，或起始点库位无绑定托盘");
        }
        #endregion 
    }
}
